#include "wxwidgetsresfactory.h"
#include "wxsdialogres.h"
#include "wxsscrollingdialogres.h"
#include "wxsframeres.h"
#include "wxspanelres.h"
#include "wxsnewwindowdlg.h"
#include "wxsitemfactory.h"
#include "wxwidgetsgui.h"
#include "../wxsresourcetree.h"
#include "../wxsmith.h"
#include <wx/choicdlg.h>
#include <tinywxuni.h>
#include <sqplus.h>
#include <sc_base_types.h>

namespace {
  wxWidgetsResFactory Factory;

  enum Resources {
    wxDialogId = 0,
    wxScrollingDialogId,
    wxFrameId,
    wxPanelId,

    ResourcesCount
  };

  const wxChar* NamesPtr[ResourcesCount] = {
    _T( "wxDialog" ),
    _T( "wxScrollingDialog" ),
    _T( "wxFrame" ),
    _T( "wxPanel" )
  };

  wxArrayString Names( ResourcesCount, NamesPtr );
  WX_DEFINE_ARRAY( TiXmlElement*, wxArrayElement );
  void AddWxExtensions( M_Code_Project* Project, const wxString& AppSource, const wxString& MainResSource, const wxString& MainResHeader, const wxString& WxsFile ) {
    wxsProject* WxsProject = wxSmith::Get()->GetSmithProject( Project );
    wxString ResourceName;
    wxString ResourceType;
    TiXmlDocument Doc;
    if( TinyXML::LoadDocument( WxsProject->GetProjectPath() + WxsFile, &Doc ) ) {
      TiXmlElement* Root = Doc.RootElement();
      if( Root ) {
        if( cbC2U( Root->Value() ) == _T( "wxsmith" ) ) {
          TiXmlElement* Object = Root->FirstChildElement( "object" );
          if( Object ) {
            ResourceType = cbC2U( Object->Attribute( "class" ) );
            ResourceName = cbC2U( Object->Attribute( "name" ) );
          }
        }
      }
    }
    if( ResourceType.IsEmpty() || ResourceName.IsEmpty() ) {
      msging( _T( "无法分析新创建的Wxs文件wxSmith支持已禁用" ) );
      return;
    }
    if( Names.Index( ResourceType ) == wxNOT_FOUND ) {
      msging( _T( "新创建的Wxs文件中的资源类型不受支持wxSmith支持被禁用" ) );
      return;
    }
    wxsResource* MainResourceGeneric = wxsResourceFactory::Build( ResourceType, WxsProject );
    wxsItemRes* MainResource = wxDynamicCast( MainResourceGeneric, wxsItemRes );
    if( !MainResource ) {
      delete MainResourceGeneric;
      msging( _T( "新创建的Wxs文件中的资源类型不受支持wxSmith支持被禁用" ) );
      return;
    }
    wxsItemRes::NewResourceParams Params;
    Params.Class = ResourceName;
    Params.Src   = MainResSource;
    Params.Hdr   = MainResHeader;
    Params.Wxs   = WxsFile;
    MainResource->CreateNewResource( Params );
    WxsProject->AddResource( MainResource );
    wxWidgetsGUI* GUI = new wxWidgetsGUI( WxsProject );
    GUI->SetAppSourceFile( AppSource );
    GUI->SetInitParams( true, true );
    GUI->SetMainResourceName( ResourceName );
    GUI->RebuildApplicationCode();
    WxsProject->SetGUI( GUI );
    Project->Save();
    MainResource->EditOpen();
  }
}


wxWidgetsResFactory::wxWidgetsResFactory() {
}

void wxWidgetsResFactory::OnAttach() {
  Manager::Get()->GetScriptingManager();
  if( SquirrelVM::GetVMPtr() ) {
    SqPlus::RegisterGlobal( AddWxExtensions, "WxsAddWxExtensions" );
  }
}

void wxWidgetsResFactory::OnRelease() {
  Manager::Get()->GetScriptingManager();
  HSQUIRRELVM v = SquirrelVM::GetVMPtr();
  if( v ) {
    sq_pushroottable( v );
    sq_pushstring( v, "WxsAddWxExtensions", -1 );
    sq_deleteslot( v, -2, false );
    sq_poptop( v );
  }
}

int wxWidgetsResFactory::OnGetCount() {
  return ResourcesCount;
}

void wxWidgetsResFactory::OnGetInfo( int Number, wxString& Name, wxString& GUI ) {
  GUI = _T( "wxWidgets" );
  Name = NamesPtr[Number];
}

wxsResource* wxWidgetsResFactory::OnCreate( int Number, wxsProject* Project ) {
  switch( Number ) {
    case wxDialogId:
      return new wxsDialogRes( Project );
    case wxScrollingDialogId:
      return new wxsScrollingDialogRes( Project );
    case wxFrameId:
      return new wxsFrameRes( Project );
    case wxPanelId:
      return new wxsPanelRes( Project );
    default:
      break;
  }
  return 0;
}

bool wxWidgetsResFactory::OnCanHandleExternal( const wxString& FileName ) {
  return wxFileName( FileName ).GetExt().Upper() == _T( "XRC" );
}

wxsResource* wxWidgetsResFactory::OnBuildExternal( const wxString& FileName ) {
  TiXmlDocument Doc;
  if( !TinyXML::LoadDocument( FileName, &Doc ) ) {
    return 0;
  }
  wxArrayString ResourcesFound;
  wxArrayElement XmlElements;
  TiXmlElement* Res = Doc.FirstChildElement( "resource" );
  if( !Res ) {
    return 0;
  }
  for( TiXmlElement* Object = Res->FirstChildElement( "object" ); Object; Object = Object->NextSiblingElement( "object" ) ) {
    wxString Class = cbC2U( Object->Attribute( "class" ) );
    wxString Name = cbC2U( Object->Attribute( "name" ) );
    if( !Name.empty() && Names.Index( Class ) != wxNOT_FOUND ) {
      ResourcesFound.Add( Name + _T( " (" ) + Class + _T( ")" ) );
      XmlElements.Add( Object );
    }
  }
  if( ResourcesFound.empty() ) {
    return 0;
  }
  int Choice = 0;
  if( ResourcesFound.size() > 1 ) {
    Choice = ::cbGetSingleChoiceIndex(
               _T( "There's more than one resource in this file.\n"
                   "Please select which one should be edited." ),
               _T( "Choose resource to edit" ),
               ResourcesFound );
    if( Choice < 0 ) {
      return 0;
    }
  }
  TiXmlElement* Object = XmlElements[Choice];
  if( !Object ) {
    return 0;
  }
  wxString Class = cbC2U( Object->Attribute( "class" ) );
  switch( Names.Index( Class ) ) {
    case wxDialogId:
      return new wxsDialogRes( FileName, Object );
    case wxScrollingDialogId:
      return new wxsScrollingDialogRes( FileName, Object );
    case wxFrameId:
      return new wxsFrameRes( FileName, Object );
    case wxPanelId:
      return new wxsPanelRes( FileName, Object );
    default:
      break;
  }
  return 0;
}

bool wxWidgetsResFactory::OnNewWizard( int Number, wxsProject* Project ) {
  wxsNewWindowDlg Dlg( 0, NamesPtr[Number], Project );
  return Dlg.ShowModal() == wxID_OK;
}

int wxWidgetsResFactory::OnResourceTreeIcon( int Number ) {
  const wxsItemInfo* Info = wxsItemFactory::GetInfo( Names[Number] );
  if( Info ) {
    return Info->TreeIconId;
  }
  return wxsResourceFactory::OnResourceTreeIcon( 0 );
}
